package cn.ekuma.data.dao.user.tree;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import com.openbravo.data.basic.BasicException;
import com.openbravo.data.loader.LocalRes;
import e.odbo.data.dsl.query.QBFParameter;
import e.odbo.data.dsl.query.QBFParameters;
import com.openbravo.data.user.EditorCreator;
import com.openbravo.data.user.Finder;

import e.odbo.data.dao.I_DataLogic;
import e.odbo.data.bean.I_Category;

public class BrowsableTreeDataModel extends javax.swing.tree.DefaultTreeModel{
    private boolean m_bIsAdjusting;
    private Comparator m_comparer;
    private I_DataLogic  dataLogic;
    private Class c;
    private EditorCreator filterCreator;
    
    /** Creates a new instance of BrowsableData */
    public BrowsableTreeDataModel(I_DataLogic dataLogic,Class cl, Comparator c,EditorCreator filterCreator) {
    	super(new CategoryTreeNode(null),true);
    	this.dataLogic=dataLogic;
        m_comparer = c;
        m_bIsAdjusting = false;
        this.c=cl;
        this.filterCreator=filterCreator;
    }

    public BrowsableTreeDataModel(I_DataLogic dataLogic,Class cl, Comparator c) {
       this(dataLogic,cl,c,null);
    }

    public BrowsableTreeDataModel(I_DataLogic dataLogic,Class cl,EditorCreator filterCreator) {
        this(dataLogic,cl,null,filterCreator);
     }

     public BrowsableTreeDataModel(I_DataLogic dataLogic,Class cl) {
        this(dataLogic,cl,null,null);
     }

	private void buildTreeForList(List<I_Category>  m_aData,CategoryTreeNode parent){
		if(m_aData.isEmpty())
			return;
		List<I_Category> recapt=new ArrayList();
		CategoryTreeNode temp;
		for(I_Category c:m_aData){
			if(parent.isChinad(c)){
				temp=new CategoryTreeNode(c);
				parent.insert(temp,parent.getChildCount());
			}else 
				recapt.add(c);
		}
		for(int i=0;i<parent.getChildCount();i++)
			buildTreeForList(recapt,(CategoryTreeNode) parent.getChildAt(i));
	}
	
	
	
	 public void refreshData() throws BasicException {
	       if(filterCreator==null)
	          putNewData(dataLogic.list(c));
		   else {
			   Object filter=filterCreator.createValue();
			   QBFParameters qbfParameters=null;
			   if(filter instanceof QBFParameters)
				   qbfParameters=(QBFParameters)filter;
			   else if (filter instanceof QBFParameter)
				   qbfParameters=new QBFParameters((QBFParameter)filter);
			   putNewData(dataLogic.query(c, qbfParameters));
		   }
	    }

	    public void loadData() throws BasicException {
	         refreshData();
	    }

	    public void unloadData() {
	        putNewData(null);
	    }
	    public void loadList(List l) {
	        putNewData(l);
	    }

	    public void sort(Comparator c)  {
	    }

	    public final boolean canLoadData() {
	        return dataLogic != null ;
	    }

	    public boolean canInsertData() {
	        return dataLogic != null ;
	    }

	    public boolean canDeleteData() {
	        return dataLogic != null ;
	    }

	    public boolean canUpdateData() {
	        return dataLogic != null ;
	    }

	    public final int findNext(int index, Finder f){
	        return -1;
	    }

	    
	    public final void removeRecord(CategoryTreeNode selectedObj) throws BasicException {
	        if (canDeleteData() && selectedObj!=null) {
	            if (dataLogic.delete(selectedObj.getCategory()) > 0) {
	            	removeNodeFromParent(selectedObj);
	            } else {
	                throw new BasicException(LocalRes.getIntString("exception.nodelete"));
	            }
	        } else {
	            // indice no valido
	            throw new BasicException(LocalRes.getIntString("exception.nodelete"));
	        }
	    }

	    public final void updateRecord(CategoryTreeNode selectedObj, I_Category value, int index) throws BasicException {
	        if (canUpdateData() && selectedObj!=null) {
	            if (dataLogic.update(value) > 0) {
	            	CategoryTreeNode srcParent=(CategoryTreeNode) selectedObj.getParent();
	            	CategoryTreeNode desParent=(CategoryTreeNode) root;
	            	if(value.getM_sParentID()!=null)
	            		desParent=findChinNodeForCategoryId(desParent, value.getM_sParentID());
	            	if(!srcParent.equals(desParent)){
	            		insertNodeInto(selectedObj,desParent,desParent.getChildCount());
	                    Object[]         removedArray = new Object[1];
	                    int[]            childIndex = new int[1];
	                    childIndex[0]=index;
	                    removedArray[0] = selectedObj;
	                    nodesWereRemoved(srcParent, childIndex, removedArray);
	            	}else
	            		this.nodeChanged(selectedObj);
	            } else {
	                // fallo la actualizacion
	                throw new BasicException(LocalRes.getIntString("exception.noupdate"));
	            }
	        } else {
	            // registro invalido
	            throw new BasicException(LocalRes.getIntString("exception.noupdate"));
	        }
	    }
	    public final void insertRecord(I_Category value) throws BasicException {
	        if (canInsertData() && dataLogic.insert(value) > 0) {
	        	CategoryTreeNode parent=(CategoryTreeNode) root;
	            if(value.getM_sParentID()!=null)
	            	parent=findChinNodeForCategoryId(parent,value.getM_sParentID());
	            insertNodeInto(new CategoryTreeNode(value), parent, parent.getChildCount());
	        } else {
	            throw new BasicException(LocalRes.getIntString("exception.noinsert"));
	        }
	    }

	  private final void putNewData(List<I_Category> aData) {
		  CategoryTreeNode root1=new CategoryTreeNode(null);
	       if(aData!=null)
	    	   buildTreeForList(aData,root1);
	      setRoot(root1);
	   }

	  
	  private CategoryTreeNode findChinNodeForCategoryId(CategoryTreeNode parent,String id){
		  CategoryTreeNode node=null;
		  for(int i=0;i<parent.getChildCount();i++){
			  node=(CategoryTreeNode) parent.getChildAt(i);
			  if(id.equalsIgnoreCase(node.getCategory().getID()))
				  return node;
		  }
		  for(int i=0;i<parent.getChildCount();i++){
			  node= findChinNodeForCategoryId((CategoryTreeNode) parent.getChildAt(i),id);
			  if(node!=null)
				  return node;
		  }
		  return null;
	  }
	
	public static class CategoryTreeNode extends javax.swing.tree.DefaultMutableTreeNode{
            I_Category category;
        
		public CategoryTreeNode(I_Category category) {
			this.category = category;
		}
		
		public boolean isChinad(I_Category category1){
			boolean isChinad=false;
			if(category==null){
				if(category1.getM_sParentID()==null)
					isChinad=true;
			}else if(category.getID().equalsIgnoreCase(category1.getM_sParentID()))
				isChinad=true;
			return  isChinad;
		}

		@Override
		public boolean equals(Object obj) {
			CategoryTreeNode src=(CategoryTreeNode)obj;
			if(src!=null&&category==null&&src.getCategory()==null)
				return true;
			if(src!=null&&category!=null&&src.getCategory()!=null)
				return src.getCategory().getID().equalsIgnoreCase(category.getID());
			return false;
		}

		public I_Category getCategory() {
			return category;
		}

		public void setCategory(I_Category category) {
			this.category = category;
		}

		@Override
		public Object clone() {
			CategoryTreeNode newNode = new CategoryTreeNode(category);
			newNode.parent=this.parent;
			newNode.children=this.children;
			return newNode;
		}
	}
}
